#include "WOP_Ref_Entry.h"
#include "WOP_Obj_Entry.h"
#include "WOPM.h"
#include <cassert>
#include "Command_Agent.h"
#include "MappingEngine.h"

////============== add at 2007/08/11
#include "dummyVM.h"
//#include "rtvm/Tree_Node_rtvm.h"
//#include "rtvm/Laser_rtvm.h"
//#include "lbvm/plain_lbvm.h"
//#include "test.h"
////==============================

//這個include WOPM是經由VC ++給予的"新增include目錄"功能，把前方的路徑省略
//所以如果換其他的IDE發現路徑錯誤，請自行更改路徑。
//元件原位址:"wopm/WOPM.h"
#include <iostream>
//#include "include/MappingDialogProxy.h"
#include "DIVA_Manager.h"
using namespace std;

BOOL CALLBACK CompRefProc(HWND,UINT,WPARAM,LPARAM);
extern WOP_Entry* currentEntry;
extern xMappingTree* mTree;

extern HINSTANCE _hInst ;  // this instance is defined in DIVA_MAIN
extern HWND _hWnd ;        // this instance is defined in DIVA_Application

WOP_Ref_Entry::WOP_Ref_Entry(string s,WOP_Entry* parent){//被程式unfold出來的(top = false)
	init(s,parent);
}
WOP_Ref_Entry::WOP_Ref_Entry(string s){//user手動檢視的 (top = true)
	init(s,NULL);
}

void WOP_Ref_Entry::unfold(){//展開Ref_Entry的內容
	assert(_updated);
	WOPM* wop = WOPM::getInstance();
	//0.檢查ref的value是否合法。 這包含NULL的檢驗
	if(_value.find_first_of('@')==-1)		
		return;

	//1.檢查是否已unflod，如果en不是NULL，表示已經被展開過了，我們就不做事。
	WOP_Obj_Entry* en = (WOP_Obj_Entry*)wop->search(_value);
	if(en != NULL)
		return;
	
	//2.製作一個Obj_Entry，加入WOP中，並要求Obj作出自己的子元素
	assert(false); // under construction
	en = new WOP_Obj_Entry(_value, NULL);	
	wop->addEntry(en);	
}

bool WOP_Ref_Entry::update(){	
	/*
	很想用super(parent_path);，但是C++不支援 Orz
	------------------------------------------------------------
	*/
	if(_updated)//如果已經更新，那就跳過
		return _changed ;

	Command_Agent* ca = Command_Agent::getInstance();
	assert(_name != "?");  // a wop with name "?" should not be updated. Check who call this to find bugs 
	string newvalue = ca->getValue(_name);//向CommandAgent要求更新數值

	_updated = true ;

	if (_value == "@null@") {
		// this is the case where a new WOP_entry is initialized (see init() of WOP_entry)
		// and we do not want to deal with its change of VM and dummy VM
	
		_value = newvalue ;	
		_changed = true ;
		return _changed ;
	}

	if (newvalue != _value) {
		_changed = true ;
		_value = newvalue ;
	}
		/*
		WOPM* wop = WOPM::getInstance();
		WOP_Entry *en = WOPM::getInstance()->check_existing_objects(getVal());
			
		if (en == NULL) { 
			// en == NULL means we cannot find the object pointed by the new reference value in WOPM
			dummyVM *dummy = (dummyVM *)MappingEngine::getInstance()->get_DummyVM_from_Entry(this);
			assert(dummy != NULL); // the dummy VM should not be NULL
			dummy->setBodyVM(NULL);
			//DIVA_VM *dummyparent = dummy->getParentVM() ;
			//dummyparent->VMValueUpdated();
		} else {
			// en is not NULL, so we try to make dummy's body VM pointed to the new object
			DIVA_VM *newvm = MappingEngine::getInstance()->get_vm_by_entry(en);
			assert(newvm != NULL) ;
			dummyVM *dummy = (dummyVM *) MappingEngine::getInstance()->get_DummyVM_from_Entry(this);
			assert(dummy != NULL); // the dummy VM should not be NULL
			dummy->setBodyVM(newvm);

			//DIVA_VM *dummyparent = dummy->getParentVM() ;
			//dummyparent->VMValueUpdated();
 
			
			// en->update(getActualPath());//要求被指到的Obj_Entry更新 
		}
		
	}
	if (! _changed) {  // although the value of the reference is not changed
					   // if its pointed object is still in WOPM
		               // it should be updated as well.

		WOP_Entry *p = WOPM::getInstance()->check_existing_objects(_value);
		if (p!= NULL){ 
			_changed = p->update();
		}
	}
	*/
	return _changed ;
}
